﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GeneralDFS.DataEntity.IO;

namespace GeneralDFS.BusinessLogical.IO
{
    public class IndexFile
    {
        private static IndexFile instance;
        public Hashtable IndexFileTable;
        public static IndexFile GetInstance()
        {
            if (instance != null)
            {
                return instance;
            }
            throw new Exception("uninit instance");
        }
        public static void Init(string path)
        {
            instance = new IndexFile(path);
        }
        private IndexFile(string path)
        {
            LogUtil.LogInfo("----------Starting init IndexFile------------");
            IndexFileTable = new Hashtable();
            string indexFilePath = Path.Combine(path, "IndexFile");
            if (!System.IO.File.Exists(indexFilePath))
            {
                FileStream fs = System.IO.File.Create(indexFilePath);
                fs.Dispose();
            }
            else
            {
                FileStream fs = System.IO.File.OpenRead(indexFilePath);
                int readLength = 0;
                byte[] buff = new byte[52];
                try
                {
                    while (fs.Position < fs.Length)
                    {
                        readLength = 0;
                        while (readLength < buff.Length)
                        {
                            readLength += fs.Read(buff, readLength, buff.Length - readLength);
                        }
                        string Guid = Encoding.Default.GetString(buff, 0, 36);
                        IndexFileInfo indexFileInfo = new IndexFileInfo
                        {
                            FileLength = BitConverter.ToInt32(buff, 36),
                            OffSet = BitConverter.ToInt64(buff, 40),
                            Valid = BitConverter.ToInt32(buff, 48)
                        };
                        IndexFileTable.Add(Guid, indexFileInfo);
                    }
                }
                catch (Exception)
                {
                    Console.WriteLine("索引文件初始化错误");
                    throw;
                }
            }
            LogUtil.LogInfo("----------init IndexFile Success------------");
        }

        public void AddNewFile(string guid, IndexFileInfo indexFileInfo)
        {
            IndexFileTable.Add(guid,indexFileInfo);
        }
        /// <summary>
        /// 将文件索引表保存到磁盘里
        /// </summary>
        /// <param name="IndexFilePath"><索引文件的路径/param>
        public void SavDir(string IndexFilePath)
        {
            if(!System.IO.File.Exists(IndexFilePath))
                throw new Exception(string.Format("无效路径{0}",IndexFilePath));
            FileStream fs = System.IO.File.OpenWrite(IndexFilePath);
            lock (instance)
            {
                byte[] data = new byte[52];
                foreach (DictionaryEntry dictionaryEntry in IndexFileTable)
                {
                    byte[] guid = Encoding.Default.GetBytes(dictionaryEntry.Key.ToString());
                    IndexFileInfo indexFileInfo = dictionaryEntry.Value as IndexFileInfo;
                    guid.CopyTo(data, 0);
                    BitConverter.GetBytes(indexFileInfo.FileLength).CopyTo(data, 36);
                    BitConverter.GetBytes(indexFileInfo.OffSet).CopyTo(data, 40);
                    BitConverter.GetBytes(indexFileInfo.Valid).CopyTo(data, 48);
                    fs.Write(data, 0, data.Length);
                }
                fs.Close();
            }
        }

        /// <summary>
        /// 删除某个小文件（使他失效)
        /// </summary>
        /// <param name="guid"></param>
        public void DeleteSmallFile(string guid)
        {
            IndexFileInfo indexFileInfo = IndexFileTable[guid] as IndexFileInfo;
            indexFileInfo.Valid = 0;
        }

    }
}
